package thread;

/**
 * 使用当前类演示并发安全问题
 *
 * 当多个线程并发操作统一临界资源，由于线程切换时机不确定，导致操作顺序出现混乱而导致的不良后果
 *
 * 临界资源：操作该资源的过程同一时刻只应被单线程进行,比如账户余额，比如火车票抢票系统
 */

public class Bank {
    //定义某人账号里的余额（定义成属性，实际上应当是在数据库中保存的）
    //注意：以下方法都不是构造方法（没有与类同名的）
    private int account = 20000;
    /**
     * 取款方法
     * @param money 取款金额
     * @return      是否允许出钞
     *
     * getMoney方法被synchronized修饰后，就只有一个线程完整的将该方法执行完毕，
       其他线程菜可以进到方法内执行。
       即：该方法不能被同时多个线程占用，解决了并发安全问题

       synchronized
       "同步的，同步化的"
       将多个线程并发操作改为同步执行
       同步执行：线程有先后顺序的排队执行
     */
    public synchronized boolean getMoney(int money){
        //1.查账
        int account = getAccount();
        //2.判断余额是否足够,取钱,记账
        if(account>=money){
            account=account-money;
            Thread.yield();//放弃时间片，模拟线程执行到saveAccount之前cpu给的时间用完了而发生线程切换
            saveAccount(account);//记账
            return true;
        } else {
            return false;
        }
    }

    //查账方法
    public int getAccount(){ return account;}
    //记账方法
    public void saveAccount(int account){ this.account= account; }
}
